package utils

import (
	"sync"
)

type SafeList struct {
	lock *sync.RWMutex
	list []interface{}
}

func NewSafeList() *SafeList {
	rval := &SafeList{
		lock: new(sync.RWMutex),
		list: make([]interface{}, 0, 1024),
	}
	return rval
}

func (this *SafeList) Add(val interface{}) {
	this.lock.Lock()
	this.list = append(this.list, val)
	this.lock.Unlock()
}

// 移除一个Listener, 注意传入的必须是添加时返回的指针
func (this *SafeList) Remove(val interface{}) bool {
	this.lock.Lock()
	defer this.lock.Unlock()
	key := -1
	for k, item := range this.list {
		if item == val {
			key = k
			break
		}
	}
	if key != -1 {
		this.list = append(this.list[:key], this.list[key+1:]...)
		return true
	} else {
		return false
	}
}

/*
**

	true: 存在
	false: 不存在
*/
func (this *SafeList) Exists(val interface{}) bool {
	this.lock.RLock()
	defer this.lock.RUnlock()
	for _, item := range this.list {
		if item == val {
			return true
		}
	}
	return false
}

/*
**

	true: 添加成功
	false: 已经存在
*/
func (this *SafeList) AddIfNoExists(val interface{}) bool {
	this.lock.Lock()
	defer this.lock.Unlock()
	key := -1
	for k, item := range this.list {
		if item == val {
			key = k
			break
		}
	}

	if key == -1 {
		this.list = append(this.list, val)
		return true
	}
	return false
}

func (this *SafeList) Clear() {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.list = make([]interface{}, 0, 1024)
}

func (this *SafeList) ForEach(cb func(val interface{})) {
	// range 相当于copy了一份新的，我想应该不需要加锁
	//  2018-07-25 10:27:29
	//this.lock.RLock()
	//objs := make([]interface{}, 0, len(this.list))
	//for _, itm := range this.list {
	//	objs = append(objs, itm);
	//}
	//this.lock.RUnlock()
	//
	//for _, itm := range objs {
	//	cb(itm)
	//}

	for _, itm := range this.list {
		cb(itm)
	}
}

func (this *SafeList) Range(cb func(val interface{}) bool) {
	// range 相当于copy了一份新的，我想应该不需要加锁
	//  2018-07-25 10:27:29
	//this.lock.RLock()
	//defer this.lock.RUnlock()
	//for _, itm := range this.list {
	//	if !cb(itm){
	//		return;
	//	}
	//}

	for _, itm := range this.list {
		if !cb(itm) {
			return
		}
	}
}

func (this *SafeList) Count() int {
	this.lock.RLock()
	defer this.lock.RUnlock()
	return len(this.list)

}
